"""
键位识别系统

整合KNN分类器和候选键生成功能
"""

import numpy as np
from typing import List, Tuple, Dict, Optional
from loguru import logger
from .knn_classifier import KNNClassifier


class KeyRecognitionSystem:
    """键位识别系统"""
    
    def __init__(self, 
                 confidence_threshold: float = 0.7,
                 max_candidates: int = 3,
                 voting_method: str = "weighted"):
        """
        初始化键位识别系统
        
        Args:
            confidence_threshold: 置信度阈值
            max_candidates: 最大候选数
            voting_method: 投票方法
        """
        self.confidence_threshold = confidence_threshold
        self.max_candidates = max_candidates
        self.voting_method = voting_method
        
        # 初始化分类器
        self.classifier = KNNClassifier()
        
        logger.info("键位识别系统初始化完成")
    
    def train(self, X: np.ndarray, y: np.ndarray, feature_names: Optional[List[str]] = None):
        """
        训练识别系统
        
        Args:
            X: 特征矩阵
            y: 标签向量
            feature_names: 特征名称列表
        """
        self.classifier.fit(X, y, feature_names)
        logger.info(f"键位识别系统训练完成，样本数={len(X)}，类别数={len(set(y))}")
    
    def recognize_key(self, feature_vector: np.ndarray) -> List[Tuple[str, float]]:
        """
        识别键位
        
        Args:
            feature_vector: 特征向量
            
        Returns:
            候选键列表 [(键位, 置信度), ...]
        """
        if not self.classifier.is_trained:
            logger.warning("分类器尚未训练")
            return [("unknown", 0.0)]
        
        # 预测候选键
        candidates = self.classifier.predict_with_confidence(
            feature_vector.reshape(1, -1),
            max_candidates=self.max_candidates
        )
        
        # 过滤低置信度候选
        filtered_candidates = [
            (key, conf) for key, conf in candidates
            if conf >= self.confidence_threshold
        ]
        
        # 如果没有满足阈值的候选，返回最高置信度的
        if not filtered_candidates:
            filtered_candidates = candidates[:1]
        
        return filtered_candidates
    
    def get_confidence_score(self, feature_vector: np.ndarray, target_key: str) -> float:
        """
        获取特定键位的置信度
        
        Args:
            feature_vector: 特征向量
            target_key: 目标键位
            
        Returns:
            置信度分数
        """
        if not self.classifier.is_trained:
            return 0.0
        
        # 获取预测概率
        probabilities = self.classifier.predict_proba(feature_vector.reshape(1, -1))
        
        # 找到目标键位的索引
        if target_key in self.classifier.classes_:
            key_index = list(self.classifier.classes_).index(target_key)
            return probabilities[0, key_index]
        else:
            return 0.0
    
    def get_nearest_neighbors(self, feature_vector: np.ndarray, n_neighbors: int = 5) -> Tuple[np.ndarray, np.ndarray]:
        """
        获取最近邻居
        
        Args:
            feature_vector: 特征向量
            n_neighbors: 邻居数量
            
        Returns:
            (距离数组, 索引数组)
        """
        if not self.classifier.is_trained:
            return np.array([]), np.array([])
        
        return self.classifier.get_neighbors(feature_vector.reshape(1, -1), n_neighbors)
    
    def evaluate_performance(self, X_test: np.ndarray, y_test: np.ndarray) -> Dict:
        """
        评估系统性能
        
        Args:
            X_test: 测试特征矩阵
            y_test: 测试标签向量
            
        Returns:
            评估结果字典
        """
        if not self.classifier.is_trained:
            logger.warning("分类器尚未训练，无法评估")
            return {}
        
        return self.classifier.evaluate(X_test, y_test)
    
    def save_model(self, filepath: str):
        """
        保存模型
        
        Args:
            filepath: 保存路径
        """
        self.classifier.save_model(filepath)
    
    def load_model(self, filepath: str):
        """
        加载模型
        
        Args:
            filepath: 模型文件路径
        """
        self.classifier.load_model(filepath)
    
    def get_system_info(self) -> Dict:
        """
        获取系统信息
        
        Returns:
            系统信息字典
        """
        info = {
            'confidence_threshold': self.confidence_threshold,
            'max_candidates': self.max_candidates,
            'voting_method': self.voting_method,
            'classifier_info': self.classifier.get_model_info()
        }
        
        return info
    
    def __str__(self) -> str:
        status = "已训练" if self.classifier.is_trained else "未训练"
        return f"KeyRecognitionSystem(threshold={self.confidence_threshold}, status={status})"
    
    def __repr__(self) -> str:
        return self.__str__() 